home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_mac.hqx / SRGP port to 5.0 (compressed) / SRGP_SPHIGS Root / MacSPHIGS / sph_input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-13  |  10.0 KB  |  436 lines

  1. #include "HEADERS.h"
  2. #include  "sphigslocal.h"
  3.  
  4. #include "sph_input.proto.h"
  5. static void ConvertLocatorMeasure(locator_measure *, srgp__locator_measure *);
  6. static int Outcode(srgp__point);
  7. static boolean LineCrossesEpsilonSquare(srgp__point, srgp__point);
  8. static boolean PtInPolygon(int, vertex_index *, srgp__point *);
  9. static boolean PtOnPolygon(int, vertex_index *, srgp__point *);
  10. static boolean TraverseStruct(int);
  11.  
  12.  
  13. static void ConvertLocatorMeasure 
  14.    (locator_measure *lm, srgp__locator_measure *slm)
  15. {
  16.    register i;
  17.  
  18.    /* SIMPLY COPY THE PORTIONS THAT NEED NO CONVERSION */
  19.    bcopy (slm->button_chord, lm->button_chord, sizeof(slm->button_chord));
  20.    slm->button_of_last_transition = lm->button_of_last_transition;
  21.  
  22.    /* TRANSLATE srgp/pdc TO npc */
  23.    lm->position[X] = (double)(slm->position.x) / SPH_ndcSpaceSizeInPixels;
  24.    lm->position[Y] = (double)(slm->position.y) / SPH_ndcSpaceSizeInPixels;
  25.    lm->position[Z] = 0.0;
  26.  
  27.    /* FIND THE RELEVANT VIEW INDEX:
  28.       I will give higher-indexed views first priority, but ignore any
  29.       views that have nothing posted to them.
  30.       But, 0 will be returned if nothing else fits the bill. */
  31.    for (i=MAX_VIEW_INDEX; i>=0; i--)
  32.       if (GEOM_ptInRect(slm->position, SPH_viewTable[i].pdc_viewport))
  33.      if (SPH_viewTable[i].highestOverlapNetwork)
  34.         break;
  35.    lm->view_index = i;
  36. }
  37.  
  38.  
  39.  
  40. void SPH_getLocator (locator_measure* lm)
  41. {
  42.    srgp__locator_measure slm;
  43.  
  44.    SRGP_getLocator (&slm);
  45.    ConvertLocatorMeasure (lm, &slm);
  46. }
  47.  
  48.  
  49.  
  50. void SPH_sampleLocator (locator_measure* lm)
  51. {
  52.    srgp__locator_measure slm;
  53.  
  54.    SRGP_sampleLocator (&slm);
  55.    ConvertLocatorMeasure (lm, &slm);
  56. }
  57.  
  58. void SPH_setLocatorMeasure (point position)
  59. {
  60.    srgp__point spt;
  61.    register i;
  62.  
  63.    /* TRANSLATE npc TO srgp/pdc */
  64.    spt.x = position[X] * SPH_ndcSpaceSizeInPixels;
  65.    spt.y = position[Y] * SPH_ndcSpaceSizeInPixels;
  66.  
  67.    SRGP_setLocatorMeasure (spt);
  68. }
  69.  
  70.  
  71. void SPH_setKeyboardEchoOrigin (point position)
  72. {
  73.    srgp__point spt;
  74.    register i;
  75.  
  76.    /* TRANSLATE npc TO srgp/pdc */
  77.    spt.x = position[X] * SPH_ndcSpaceSizeInPixels;
  78.    spt.y = position[Y] * SPH_ndcSpaceSizeInPixels;
  79.  
  80.    SRGP_setKeyboardEchoOrigin (spt);
  81. }
  82.  
  83.  
  84. /** CORRELATION ROUTINES
  85. **/
  86.  
  87. static srgp__rectangle epsilonSquare;
  88.  
  89.  
  90. static int Outcode (srgp__point pt)
  91. {
  92.    int outcode;
  93.  
  94.    if (pt.x > epsilonSquare.top_right.x)
  95.       outcode = 2;
  96.    else if (pt.x < epsilonSquare.bottom_left.x)
  97.       outcode = 1;
  98.    else
  99.       outcode = 0;
  100.  
  101.    if (pt.y > epsilonSquare.top_right.y)
  102.       outcode += 8;
  103.    else if (pt.y < epsilonSquare.bottom_left.y)
  104.       outcode += 4;
  105.  
  106.    return outcode;
  107. }
  108.  
  109.  
  110. static boolean IsPowerOfTwo[] = {
  111.    FALSE,        /*  0 */
  112.    TRUE,        /*  1 */
  113.    TRUE,        /*  2 */
  114.    FALSE,        /*  3 */
  115.    TRUE,        /*  4 */
  116.    FALSE,        /*  5 */
  117.    FALSE,        /*  6 */
  118.    FALSE,        /*  7 */
  119.    TRUE,        /*  8 */
  120.    FALSE,        /*  9 */
  121.    FALSE,        /* 10 */
  122.    FALSE,        /* 11 */
  123.    FALSE,        /* 12 */
  124.    FALSE,        /* 13 */
  125.    FALSE,        /* 15 */
  126.    TRUE            /* 16 */
  127. };
  128.  
  129.  
  130.  
  131.  
  132. static boolean
  133. LineCrossesEpsilonSquare (srgp__point pt1, srgp__point pt2)
  134. {
  135.    enum {UNKNOWN, YES, NO} doesCross = UNKNOWN;
  136.    int outcode1, outcode2;
  137.  
  138.  
  139.    do {
  140.       outcode1 = Outcode (pt1);
  141.       outcode2 = Outcode (pt2);
  142.  
  143.       if ((outcode1 & outcode2) > 0) 
  144.      doesCross = NO;
  145.       else if ((outcode1==0) || (outcode2==0)) 
  146.      doesCross = YES;
  147.       else if ((IsPowerOfTwo[outcode1]) && (IsPowerOfTwo[outcode2])) {
  148.      if ((outcode1 ^ outcode2) == 3)
  149.         doesCross = YES;
  150.      else if ((outcode1 ^ outcode2) == 12)
  151.         doesCross = YES;
  152.       }
  153.  
  154.       if (doesCross == UNKNOWN) {
  155.      if ((outcode1 & 8) != 0) {
  156.         pt1.x += ((pt2.x-pt1.x)*(epsilonSquare.top_right.y-pt1.y))/
  157.            (pt2.y-pt1.y);
  158.         pt1.y = epsilonSquare.top_right.y;
  159.      }
  160.      else if ((outcode1 & 4) != 0) {
  161.         pt1.x += ((pt2.x-pt1.x)*(epsilonSquare.bottom_left.y-pt1.y))/
  162.            (pt2.y-pt1.y);
  163.         pt1.y = epsilonSquare.bottom_left.y;
  164.      }
  165.      else if ((outcode1 & 2) != 0) {
  166.         pt1.y += ((pt2.y-pt1.y)*(epsilonSquare.top_right.x-pt1.x))/
  167.            (pt2.x-pt1.x);
  168.         pt1.x = epsilonSquare.top_right.x;
  169.      }
  170.      else if ((outcode1 & 1) != 0) {
  171.         pt1.y += ((pt2.y-pt1.y)*(epsilonSquare.bottom_left.x-pt1.x))/
  172.            (pt2.x-pt1.x);
  173.         pt1.x = epsilonSquare.bottom_left.x;
  174.      }
  175.       }
  176.    }
  177.    while (doesCross == UNKNOWN);
  178.  
  179.    return (doesCross == YES);
  180. }
  181.       
  182.  
  183.  
  184. static boolean 
  185. PtInPolygon (int vertcount, vertex_index *vertindexlist, srgp__point *verts)
  186. {
  187.    int hitcount = 0;
  188.    int codecur, codeprev, codeLOOK;
  189.    int jcur, jprev;
  190.    double m, b;
  191.    srgp__point ptcur, ptprev;
  192.    register i;
  193.  
  194.  
  195.    jcur = 0;
  196.    ptcur = verts[vertindexlist[jcur]];
  197.    codecur = Outcode (ptcur);
  198.  
  199.    for (i=1; i<=vertcount; i++) {
  200.       jprev = jcur;
  201.       codeprev = codecur;
  202.       ptprev = ptcur;
  203.       
  204.       if (i==vertcount)
  205.      jcur = 0;
  206.       else
  207.      jcur = i;
  208.       
  209.       ptcur = verts[vertindexlist[jcur]];
  210.       codecur = Outcode (ptcur);
  211.  
  212.       /* FIRST, CHECK FOR SPECIAL CASE OF A VERTEX ON THE RAY ITSELF. */
  213.       if ((codecur == 2) || (codeprev == 2)) {     /* if  *on* the ray! */
  214.      if (ptcur.y < ptprev.y)
  215.         codeLOOK = codecur;
  216.      else
  217.         codeLOOK = codeprev;
  218.      if ((codeLOOK == 2) && (codecur != codeprev))
  219.         hitcount++;
  220.  
  221.      continue;   /* don't go into the switch statement */
  222.       }
  223.       
  224.       switch (codecur & codeprev) {
  225.        case 1:
  226.        case 4:
  227.        case 5:
  228.        case 6:
  229.        case 8:
  230.        case 9:
  231.        case 10:
  232.      /* TRIVIAL REJECT */
  233.      break;
  234.        case 2:
  235.      /* TRIVIAL ACCEPT */
  236.      hitcount++;
  237.      break;
  238.        default:
  239.      if (((codecur | codeprev) & 3) == 0) {
  240.         /* THE prev->cur LINE ACTUALLY PASSES THROUGH THE pdcpt !!! */
  241.         /* IGNORE IT!!! */
  242.      }
  243.      else {
  244. #           define pdcpt   (epsilonSquare.bottom_left)
  245.         m = ((double)ptprev.y-ptcur.y) / ((double)ptprev.x-ptcur.x);
  246.         b = (double)ptprev.y - (m*ptprev.x);
  247.         if ( (((double)pdcpt.y - b) / m ) >= (double)pdcpt.x)
  248.            hitcount++;
  249. #           undef pdcpt
  250.      }
  251.       }
  252.    }
  253.    
  254.    return ((hitcount % 2) == 1);
  255. }
  256.  
  257.  
  258.  
  259.       
  260.  
  261.  
  262. static boolean 
  263. PtOnPolygon (int vertcount, vertex_index *vertindexlist, srgp__point *verts)
  264. {
  265.    int jcur, jprev;
  266.    srgp__point ptcur, ptprev;
  267.    register i;
  268.  
  269.  
  270.    jcur = 0;
  271.    ptcur = verts[vertindexlist[jcur]];
  272.  
  273.    for (i=1; i<=vertcount; i++) {
  274.       jprev = jcur;
  275.       ptprev = ptcur;
  276.       
  277.       if (i==vertcount)
  278.      jcur = 0;
  279.       else
  280.      jcur = i;
  281.       
  282.       ptcur = verts[vertindexlist[jcur]];
  283.  
  284.       if (LineCrossesEpsilonSquare (ptcur, ptprev))
  285.      return TRUE;
  286.    }
  287.  
  288.    return FALSE;
  289. }
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296. static boolean hit_was_made;
  297. static unsigned short cur_traversal_index, hit_traversal_index;
  298. static pickInformation *INFO;
  299.  
  300.  
  301.  
  302.  
  303. static boolean TraverseStruct (int structID)
  304. {
  305.    register element *curel;
  306.  
  307.    pickPathItem *curpitem = &(INFO->path[INFO->pickLevel++]);
  308.  
  309.    curpitem->structureID = structID;
  310.    curpitem->elementIndex = 0;
  311.    curpitem->pickID = 0;
  312.  
  313.    for /* FOR EACH ELEMENT IN THE STRUCTURE, IN ORDER: */
  314.       (curel = SPH__structureTable[structID].first_element;
  315.        curel;
  316.        curel = curel->next) {
  317.      curpitem->elementIndex++;
  318.      switch (curel->type) {
  319.       case ELTYP__PICK_ID:
  320.         curpitem->pickID = curel->data.value;
  321.         break;
  322.       case ELTYP__POLYHEDRON:
  323.       case ELTYP__FILL_AREA:
  324.         if (cur_traversal_index++ == hit_traversal_index) {
  325.            /******* !!!!!!!!!!!! C O R R E L A T I O N !!!!!!!!!!!! ******/
  326.            SRGP_beep();
  327.            curpitem->elementType = curel->type;
  328.            return TRUE;
  329.         }
  330.         break;
  331.       case ELTYP__EXECUTE_STRUCTURE:
  332.         if (TraverseStruct (curel->data.value)) {
  333.            curpitem->elementType = curel->type;
  334.            return TRUE;
  335.         }
  336.      }
  337.       }
  338.  
  339.    /* Well, we didn't make a correlate happen in this structure! */
  340.    INFO->pickLevel--;
  341.    return FALSE;
  342. }
  343.  
  344.  
  345.  
  346.  
  347.  
  348. void SPH_pickCorrelate (point npc_position, int viewindex, 
  349.             pickInformation *pickinfo)
  350. {
  351.    srgp__point pdcpoint;
  352.    register obj *curobj;
  353.    root_header *root;
  354.    view_spec *vs = &(SPH_viewTable[viewindex]);
  355.    boolean (*correlator)();
  356.  
  357.  
  358.    /* IF THE POINT IS OUTSIDE ALL KNOWN VIEWPORTS */
  359.    if (viewindex < 0) {
  360.       pickinfo->pickLevel = 0;
  361.       return;
  362.    }
  363.       
  364.    
  365.    if (vs->obsolete_object_list || vs->obsolete_pdc_vertices)
  366.       SPH__error (ERR_PICK_CORR_WITH_UNSYNCH_DISPLAY);
  367.  
  368.    if (vs->rendermode == WIREFRAME_RAW)
  369.       SPH__error (ERR_PICK_CORR_WITH_WIRE_RAW);
  370.  
  371.  
  372.    /********* CONVERT NPC PICK POINT TO srgp COORDS. */
  373.    pdcpoint.x = npc_position[X] * SPH_ndcSpaceSizeInPixels;
  374.    pdcpoint.y = npc_position[Y] * SPH_ndcSpaceSizeInPixels;
  375.  
  376.    /********* SET THE EPSILON SQUARE STATIC
  377.     The way it is set depends upon the type of correlation that will be done:
  378.     for PtInPolygon, it should be a square of 0 area. */
  379.    epsilonSquare.bottom_left = pdcpoint;
  380.    epsilonSquare.top_right = pdcpoint;
  381.    correlator = PtInPolygon;
  382.    if (vs->rendermode == WIREFRAME) {
  383.       epsilonSquare.bottom_left.x--;
  384.       epsilonSquare.bottom_left.y--;
  385.       epsilonSquare.top_right.x++;
  386.       epsilonSquare.top_right.y++;
  387.       correlator = PtOnPolygon;
  388.    }
  389.  
  390.  
  391.    /********** FIRST, SCAN BACKWARDS THROUGH THE OBJECT LIST. 
  392.      Optimization bug!  We can't scan backwards, because the object
  393.      list currently is singly linked.  All I can do is scan forwards
  394.      and I have to examine EVERYTHING in the list unconditionally!
  395.      */
  396.    hit_was_made = FALSE;   /* ...until proven guilty */
  397.  
  398.    for (curobj = vs->objects;
  399.     curobj != NULL;
  400.     curobj = curobj->next) {
  401.       if (correlator
  402.           (curobj->data.face.numPoints,
  403.           curobj->data.face.points,
  404.           vs->pdcVertices)) {
  405.      /********** !!!!!!!!!!!  H I T !!!!!!!!!!!!! ************/
  406.      hit_was_made = TRUE;
  407.      hit_traversal_index = curobj->traversal_index;
  408.       }
  409.    }
  410.  
  411.  
  412.    if (FALSE == hit_was_made) {
  413.       pickinfo->pickLevel = 0;
  414.       return;
  415.    }
  416.  
  417.  
  418.    /***** NOW, WE KNOW THE UNIQUE TRAVERSAL INDEX OF THE PRIMITIVE SELECTED.
  419.      We must traverse the network speedily (honoring only the
  420.      execution elements) looking for the primitive having that index, keeping
  421.      a stack with the pick information in it.
  422.      */
  423.  
  424.    cur_traversal_index = 0;
  425.    INFO = pickinfo;
  426.  
  427.    for
  428.       (root = vs->lowestOverlapNetwork;
  429.        root != NULL;
  430.        root = root->nextHigherOverlapRoot) {
  431.      INFO->pickLevel  = 0;
  432.      if (TraverseStruct (root->root_structID))
  433.         break;
  434.       }
  435. }
  436.